#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <aio.h>
#include <signal.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <pthread.h>
#include <stdatomic.h>
#include <semaphore.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/time.h>

#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)

#define BLKSZ 16384
#define BLK_BITS 12
#define PATH_LEN 64

int p;
#define NROW (p - 1)
#define NCOL p
#define MSIZE (NROW * NCOL)
#define REAL_MSIZE (NROW * (NCOL + 2))
#define MAX_BAD_DISK 2
#define COL_VALID(valid_blk, col) ((valid_blk - col - 1 + NCOL) / NCOL) // 计算一个列有多少有效块

// typedef struct {
//     uint32_t disk;
//     uint32_t lbn; // 在当前disk中的block偏移
//     // size_t valid_size; 由于文件只会是BLKSZ的整数倍, 故此字段无用
//     char *data;
// } block_t;

#define NTHREAD 8
typedef struct {
    off_t start;
    off_t fileSz;
    int step;
    int idx0, idx1;
} thread_param_t;

// atomic_long wCnt_atomic = ATOMIC_VAR_INIT(0);
// sem_t wFinish;

int file_fd;
int *data_fds;
// block_t *blocks;

inline ssize_t fast_read(int fd, void *buf, size_t nbytes, off_t offset) {
    ssize_t ret;
    if (unlikely((ret = pread(fd, buf, nbytes, offset)) < 0)) {
        perror("read");
        exit(1);
    }
    return ret;
}

inline void fast_read_check(int fd, void *buf, size_t nbytes, off_t offset) {
    ssize_t ret;
    if (unlikely((ret = fast_read(fd, buf, nbytes, offset)) != nbytes)) {
        perror("fast_read_check");
        fprintf(stderr, "fast_read_check error: %ld != %ld\n", ret, nbytes);
        exit(1);
    }
}

inline ssize_t fast_write(int fd, void *buf, size_t nbytes, off_t offset) {
    ssize_t ret;
    if (unlikely((ret = pwrite(fd, buf, nbytes, offset)) < 0)) {
        perror("write");
        exit(1);
    }
    return ret;
}
/*
void aio_completion_handler(sigval_t sigval) {
    struct aiocb *result = (struct aiocb *)sigval.sival_ptr;
    if (unlikely(aio_error(result))) {
        perror("aio_error");
        fprintf(stderr, "aio_error: %s\n", strerror(aio_error(result)));
    } else {
        if (aio_return(result) != result->aio_nbytes) {
            perror("aio_return");
            printf("write error: %ld != %ld\n", aio_return(result), result->aio_nbytes);
        }
        atomic_fetch_sub(&wCnt_atomic, 1);
        sem_post(&wFinish);
        free(result->aio_buf);
    }
}
*/

inline void fast_write_check(int fd, void *buf, size_t nbytes, off_t offset) {
    /*
    struct aiocb *aio = calloc(1, sizeof(struct aiocb));
    void *tmp = malloc(nbytes);
    memcpy(tmp, buf, nbytes);
    // 基础设置
    aio->aio_fildes = fd;
    aio->aio_buf = tmp;
    aio->aio_nbytes = nbytes;
    aio->aio_offset = offset;
    // 回调函数设置
    aio->aio_sigevent.sigev_notify = SIGEV_THREAD;
    aio->aio_sigevent.sigev_notify_function = aio_completion_handler;
    aio->aio_sigevent.sigev_notify_attributes = NULL;
    aio->aio_sigevent.sigev_value.sival_ptr = aio;
    // 提交异步执行
    atomic_fetch_add(&wCnt_atomic, 1); // 每次提交异步操作时增加计数
    aio_write(aio);
    */
    ssize_t ret;
    if (unlikely((ret = fast_write(fd, buf, nbytes, offset)) != nbytes)) {
        perror("fast_write_check");
        fprintf(stderr, "write error: %ld != %ld\n", ret, nbytes);
        exit(1);
    }
}

inline int OpenMode(const char *pathname, int flags, mode_t mode) {
    int fd = open(pathname, flags, mode);
    if (unlikely(fd < 0)) {
        perror("open");
        exit(-1);
    }
    return fd;
}

inline int Open(const char *pathname, int flags) {
    int fd = open(pathname, flags);
    if (unlikely(fd < 0)) {
        perror("open");
        exit(-1);
    }
    return fd;
}

inline off_t FileSize(int fd) {
    struct stat st;
    if (unlikely(fstat(fd, &st) < 0)) {
        perror("fstat");
        exit(-1);
    }
    return st.st_size;
}
